package org.sbbs.tool;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.Validation;
import javax.validation.ValidatorFactory;

import org.hibernate.validator.internal.metadata.BeanMetaDataManager;
import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
import org.hibernate.validator.internal.metadata.core.MetaConstraint;
import org.hibernate.validator.internal.metadata.location.BeanConstraintLocation;
import org.hibernate.validator.internal.metadata.location.MethodConstraintLocation;

public class ValidatorUtil {
	BeanMetaData mata;

	String fieldName;

	String methodName;

	String javaType;

	List<String> classVL = new ArrayList<String>();

	List<String> otherVL = new ArrayList<String>();

	public ValidatorUtil(String entityFullName) throws ClassNotFoundException, InstantiationException,
			IllegalAccessException {
		ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
		// factory.
		BeanMetaDataManager bm = new BeanMetaDataManager(new ConstraintHelper());

		// Class.forName( "DemoEntity").getClass();
		mata = bm.getBeanMetaData(Class.forName(entityFullName).newInstance().getClass());

		/*
		 * BeanMetaData mata = bm.getBeanMetaData( DemoEntity.class );
		 */

		// Set<MetaConstraint> dcs = mata.getDirectMetaConstraints();
	}

	/**
	 * @param fieldName
	 * @return
	 */
	public String getFormValidationString(String fieldName) {
		boolean typeValidation = false;
		this.fieldName = fieldName;
		this.methodName = this.getFieldMethodName(fieldName);

		Set<MetaConstraint> dcs = mata.getDirectMetaConstraints();

		for (Iterator iterator = dcs.iterator(); iterator.hasNext();) {
			MetaConstraint mc = (MetaConstraint) iterator.next();
			String fn = mc.getLocation().getMember().getName();
			if (fn.equals(this.fieldName) || fn.equals(this.methodName)) {

				if (!typeValidation) {
					String tv = this.getFieldTypeClassValidation(mc);
					if (tv != null)
						classVL.add(tv);
					typeValidation = true;
				}

				this.getFieldValidation(mc);
				// this.getFieldOtherValidation( mc );

				/*
				 * if ( cv != null ) classVL.add( cv ); if ( ov != null )
				 * otherVL.add( ov );
				 */
			}

		}

		return getFieldValidationString(this.classVL, this.otherVL);
	}

	private String getFieldMethodName(String fieldName) {
		String ms = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

		return ms;
	}

	private String getFieldTypeClassValidation(MetaConstraint mc) {
		Type t = null;
		String tClass = null;
		if (mc.getElementType().name().equals("FIELD")) {
			t = ((BeanConstraintLocation) mc.getLocation()).typeOfAnnotatedElement();
		} else {
			t = ((MethodConstraintLocation) mc.getLocation()).typeOfAnnotatedElement();
		}

		if (t != null) {
			if (t.equals(Integer.class) || t.equals(Long.class) || t.equals(Short.class) || t.equals(Byte.class))
				tClass = "digits";
			else if (t.equals(Float.class) || t.equals(Double.class))
				tClass = "number";
		}

		return tClass;
	}

	/**
	 * @param mc
	 * @return
	 */
	private String getFieldValidation(MetaConstraint mc) {
		String type = mc.getDescriptor().getAnnotation().annotationType().getName();
		// javax
		if (type.equals("javax.validation.constraints.Digits")) {

		}
		if (type.equals("javax.validation.constraints.Future")) {

		}
		if (type.equals("javax.validation.constraints.Past")) {

		}
		if (type.equals("javax.validation.constraints.DecimalMin")) {

		}
		if (type.equals("javax.validation.constraints.DecimalMax")) {

		}
		if (type.equals("javax.validation.constraints.Size")) {
			Map attrs = mc.getDescriptor().getAttributes();
			Integer min = (Integer) attrs.get("min");
			Integer max = (Integer) attrs.get("max");
			// this.classVL.add( "min" );
			// this.classVL.add( "max" );
			if (min != null)
				this.otherVL.add("minlength=" + "\"" + min + "\"");
			if (max != null)
				this.otherVL.add("maxlength=" + "\"" + max + "\"");
		}
		if (type.equals("javax.validation.constraints.NotNull")) {
			this.classVL.add("required");
		}
		if (type.equals("javax.validation.constraints.Max")) {
			Map attrs = mc.getDescriptor().getAttributes();
			Long max = (Long) attrs.get("value");
			// this.classVL.add( "max" );
			this.otherVL.add("max=" + "\"" + max + "\"");
		}
		if (type.equals("javax.validation.constraints.Min")) {
			Map attrs = mc.getDescriptor().getAttributes();
			Long min = (Long) attrs.get("value");
			// this.classVL.add( "min" );
			this.otherVL.add("min=" + "\"" + min + "\"");
		}

		// hibernate
		if (type.equals("org.hibernate.validator.constraints.NotBlank")) {
			this.classVL.add("required");
		}
		if (type.equals("org.hibernate.validator.constraints.NotEmpty")) {
			this.classVL.add("required");
		}
		if (type.equals("org.hibernate.validator.constraints.CreditCardNumber")) {

			this.classVL.add("creditcard");
		}
		if (type.equals("org.hibernate.validator.constraints.Email")) {
			this.classVL.add("email");
		}
		if (type.equals("org.hibernate.validator.constraints.URL")) {
			this.classVL.add("url");

		}
		if (type.equals("org.hibernate.validator.constraints.Length")) {
			Map attrs = mc.getDescriptor().getAttributes();
			Integer min = (Integer) attrs.get("min");
			Integer max = (Integer) attrs.get("max");
			if (min != null)
				this.otherVL.add("minlength=" + "\"" + min + "\"");
			if (max != null)
				this.otherVL.add("maxlength=" + "\"" + max + "\"");
		}

		return null;
	}

	private String getFieldOtherValidation(MetaConstraint mc) {
		/*
		 * String type =
		 * mc.getDescriptor().getAnnotation().annotationType().getName(); //
		 * javax if ( type.equals( "javax.validation.constraints.Max" ) ) { } if
		 * ( type.equals( "javax.validation.constraints.Min" ) ) { } //
		 * hibernate if ( type.equals(
		 * "org.hibernate.validator.constraints.NotEmpty" ) ) { }
		 */
		return null;
	}

	private String getFieldValidationString(List cl, List ol) {
		String cString = "\"";
		for (Iterator iterator = cl.iterator(); iterator.hasNext();) {
			String str = (String) iterator.next();
			cString = cString + " " + str;
		}
		cString = cString + "\"";

		String os = "";
		for (Iterator iterator = ol.iterator(); iterator.hasNext();) {
			String str = (String) iterator.next();
			os = os + " " + str;
		}

		return cString + " " + os;
	}

}
